// 加载路径模块
const path = require("path");
// 加载html插件
const HtmlWebpackPlugin = require("html-webpack-plugin");
// 处理css
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
// vue加载插件
const VueLoaderPlugin = require("vue-loader/lib/plugin-webpack5");
// vue客户端渲染
const VueSSRClientPlugin = require("vue-server-renderer/client-plugin");
// vue客户端渲染
const VueSSRServerPlugin = require("vue-server-renderer/server-plugin");

// 通用规则
function getModuleRules(isBundle = false) {
  let rules = [];
  // 处理图片
  rules.push(
    {
      test: /\.(png|jpg|gif)$/,
      use: [
        {
          loader: "file-loader",
          options: {
            name: "[name].[hash:8].[ext]",
            outputPath: "assets/images",
            esModule: false,
            emitFile: isBundle ? false : true
          },
        },
      ],
    });
  // 处理压缩包
  rules.push({
    test: /\.(zip|gz|rar)$/,
    use: [
      {
        loader: "file-loader",
        options: {
          name: "[name].[hash:8].[ext]",
          outputPath: "assets/zip",
          esModule: false,
          emitFile: isBundle ? false : true
        },
      },
    ],
  });
  // 处理字体
  rules.push({
    test: /\.(woff2|woff|eot|ttf|otf)$/,
    use: [
      {
        loader: "file-loader",
        options: {
          name: "[name].[hash:8].[ext]",
          outputPath: "assets/fonts",
          esModule: false,
          emitFile: isBundle ? false : true
        },
      },
    ],
  })
  // 处理vue
  rules.push({
    test: /.vue$/,
    use: [
      {
        loader: "vue-loader",
      },
    ],
  })
  // 处理html
  rules.push({
    test: /.html$/,
    use: [
      {
        loader: "raw-loader",
      },
    ],
  })
  // script 处理
  rules.push({
    test: /\.(ts|js)$/,
    use: [
      {
        loader: "esbuild-loader",
        options: {
          loader: "ts",
        },
      },
    ],
  })
  // css 和 scss 处理
  rules.push({
    test: /\.(css|scss|sass)$/,
    use: [
      !isBundle ? {
        loader: MiniCssExtractPlugin.loader,
      } : undefined,
      {
        loader: "css-loader",
        options: {
          esModule: false
        }
      },
      {
        loader: "sass-loader",
        options: {
          sourceMap: true,
        },
      },
    ].filter(item => item),
  });
  return rules;
}
// bandle配置
function bundleConfig() {
  return {
    target: "node",
    mode: "development",
    entry: {
      "server-bundle": {
        import: "./src/render/entry-server.ts",
        filename: "built-server-bundle.js",
      },
    },
    output: {
      publicPath: "/",
      path: path.resolve(process.cwd(), "dist"),
      libraryTarget: "commonjs2"
    },
    resolve: {
      extensions: [".js", ".json", ".ts", ".vue", ".scss", ".sass"],
    },
    module: {
      rules: [...getModuleRules(true)],
    },
    externalsPresets: { node: true },
    externals: {},
    plugins: [
      // 加载vue
      new VueLoaderPlugin(),
      // 加载vue服务端
      new VueSSRServerPlugin()
    ],
    devtool: "cheap-module-source-map",
  };
}
// client配置
function clientConfig() {
  return {
    target: ["web", "es5"],
    mode: "development",
    entry: {
      app: {
        import: "./src/render/entry-client.ts",
      },
    },
    output: {
      publicPath: "/",
      path: path.resolve(process.cwd(), "dist"),
      filename: "assets/js/[name].[chunkhash:8].js",
      chunkFilename: "assets/js/[chunkhash].js",
    },
    resolve: {
      extensions: [".js", ".json", ".ts", ".vue", ".scss", ".sass"],
    },
    module: {
      rules: [...getModuleRules(false)],
    },
    externalsPresets: { node: true },
    externals: {},
    plugins: [
      // 加载vue
      new VueLoaderPlugin(),
      // 加载vue客户端
      new VueSSRClientPlugin(),
      // css分离处理
      new MiniCssExtractPlugin({
        filename: "assets/css/[name].css",
        chunkFilename: "assets/css/[chunkhash].css"
      }),
      new HtmlWebpackPlugin({
        template: "./src/public/template.html",
        minify: false,
      }),
    ],
    devtool: "cheap-module-source-map",
  };
}

module.exports = {
  bundleConfig,
  clientConfig
}